/**
 * @file Buffer.hpp
 * @author 1102403684@qq.com
 * @brief 缓冲区设计，用来接收用户请求及准备发送的响应等
 * @version 0.1
 * @date 2024-10-02
 *
 * @copyright Copyright (c) 2024
 *
 */

#pragma once
#include <vector>
#include <string>

#include <cstdint>
#include <cassert>
#include <cstring>
#include <memory>

#define BUFFER_MAX_SIZE 1024 // 定义缓冲区的初始大小(字节)

class Buffer
{
public:
    using SharedPtr = std::shared_ptr<Buffer>;
    Buffer() : reader_idx_(0), writer_idx_(0), buffer_(BUFFER_MAX_SIZE) {}

    // Buffer(Buffer &&buffer)
    // {
    //     std::swap(buffer.buffer_, buffer_);
    //     std::swap(buffer.reader_idx_, reader_idx_);
    //     std::swap(buffer.writer_idx_, writer_idx_);
    //     buffer.reader_idx_ = buffer.writer_idx_ = 0;
    // }

    // Buffer(const Buffer& buffer){
        
    // }

    // Buffer &operator=(Buffer &&other)
    // {
    //     if (this != &other)
    //     {
    //         // 移动other的资源到当前对象
    //         std::swap(buffer_, other.buffer_);
    //         std::swap(reader_idx_, other.reader_idx_);
    //         std::swap(writer_idx_, other.writer_idx_);
    //         other.reader_idx_ = 0;
    //         other.writer_idx_ = 0;
    //     }
    //     return *this;
    // }

    ~Buffer() {}
    char *begin();
    char *get_writer_addr();
    char *get_reader_addr();
    uint64_t get_front_idle_size();
    uint64_t get_back_idle_size();
    uint64_t get_readable_size();
    uint64_t get_writeable_size();
    void move_read_offset(uint64_t len);
    void move_write_offset(uint64_t len);
    void ensure_enough_size(uint64_t len);

    // 写入数据
    void write(const void *data, uint64_t length);
    void write_string(const std::string &data);
    void write_buffer(Buffer data);
    void write_buffer_shared(Buffer::SharedPtr buffer);

    // 读取数据
    void read(void *buffer, uint64_t length);
    std::string read_string(uint64_t length);
    void read_pop(void *buffer, uint64_t length);
    std::string read_string_pop(uint64_t length);

    void clear();

    char *find_crlf();
    std::string get_line();
    std::string get_line_pop();

private:
    std::vector<char> buffer_;
    uint64_t reader_idx_;
    uint64_t writer_idx_;
};

//----------------Buffer implement-------------------

char *Buffer::begin()
{
    return &*(buffer_.begin());
}

char *Buffer::get_writer_addr()
{
    return begin() + writer_idx_;
}

char *Buffer::get_reader_addr()
{
    return begin() + reader_idx_;
}

uint64_t Buffer::get_front_idle_size()
{
    return reader_idx_;
}
uint64_t Buffer::get_back_idle_size()
{
    return buffer_.size() - writer_idx_;
}

uint64_t Buffer::get_readable_size()
{
    return writer_idx_ - reader_idx_;
}

uint64_t Buffer::get_writeable_size()
{
    return get_front_idle_size() + get_back_idle_size();
}

void Buffer::move_read_offset(uint64_t len)
{
    if (len == 0)
        return;
    assert(len <= get_readable_size());
    reader_idx_ += len;
}

void Buffer::move_write_offset(uint64_t len)
{
    assert(len <= get_back_idle_size());
    writer_idx_ += len;
}

void Buffer::ensure_enough_size(uint64_t len)
{
    if (get_back_idle_size() >= len)
        return;
    if (len <= get_writeable_size())
    {
        // 移动数据到起始地址
        uint64_t readable_size = get_readable_size();
        std::copy(get_reader_addr(), get_reader_addr() + readable_size, begin());
        reader_idx_ = 0;
        writer_idx_ = readable_size;
    }
    else
    {
        buffer_.resize(writer_idx_ + len);
    }
}

// 写入数据
void Buffer::write(const void *data, uint64_t length)
{
    if (length == 0)
        return;
    // 确保足够空间
    ensure_enough_size(length);
    // 拷贝
    const char *d = (const char *)data; // 因为void*没有步长
    std::copy(d, d + length, get_writer_addr());
    // 移动写位置
    move_write_offset(length);
}
void Buffer::write_string(const std::string &data)
{
    return write(data.c_str(), data.size());
}
void Buffer::write_buffer(Buffer data)
{
    return write(data.get_reader_addr(), data.get_readable_size());
}

void Buffer::write_buffer_shared(Buffer::SharedPtr buffer){
    return write(buffer->get_reader_addr(), buffer->get_readable_size());
}

// 读取数据
void Buffer::read(void *buffer, uint64_t length)
{
    assert(length <= get_readable_size());
    // TODO
    std::copy(get_reader_addr(), get_reader_addr() + length, (char *)buffer);
}
std::string Buffer::read_string(uint64_t length)
{
    assert(length <= get_readable_size());
    std::string str;
    str.resize(length);
    read(&str[0], length);
    return str;
}

void Buffer::read_pop(void *buffer, uint64_t length)
{
    read(buffer, length);
    move_read_offset(length);
}

std::string Buffer::read_string_pop(uint64_t length)
{
    std::string str = read_string(length);
    move_read_offset(length);
    return str;
}

void Buffer::clear()
{
    reader_idx_ = 0;
    writer_idx_ = 0;
}

char *Buffer::find_crlf()
{
    void *res = memchr(get_reader_addr(), '\n', get_readable_size());
    return (char *)res;
}

std::string Buffer::get_line()
{
    char *pos = find_crlf();
    if (!pos)
    {
        return "";
    }

    //+1为了取出\n | \r\n
    return read_string(pos - get_reader_addr() + 1);
}

std::string Buffer::get_line_pop()
{
    std::string res = get_line();
    move_read_offset(res.size());
    return res;
}
